home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Atari Mega Archive 1
/
Atari Mega Archive - Volume 1.iso
/
language
/
sozobon2.zoo
/
top
/
health.c
< prev
next >
Wrap
C/C++ Source or Header
|
1990-12-14
|
4KB
|
186 lines
/* Copyright (c) 1988 by Sozobon, Limited. Author: Tony Andrews
*
* Permission is granted to anyone to use this software for any purpose
* on any computer system, and to redistribute it freely, with the
* following restrictions:
* 1) No charge may be made other than reasonable charges for reproduction.
* 2) Modified versions must be clearly marked as such.
* 3) The authors are not responsible for any harmful consequences
* of using this software, even if they result from defects in it.
*/
/*
* Routines for data flow analysis by block and function.
*/
#include "top.h"
/*
* bprep() - initial analysis of a block
*/
void
bprep(bp)
BLOCK *bp;
{
register INST *ip;
register int ref, set;
ref = set = 0;
for (ip = bp->first; ip != NULL ;ip = ip->next) {
ref |= (ip->rref = reg_ref(ip)) & ~set;
set |= (ip->rset = reg_set(ip));
}
bp->rref = ref;
bp->rset = set;
}
/*
* fprep() - perform initial analysis of individual blocks in a function
*/
static void
fprep(bp)
BLOCK *bp;
{
register BLOCK *cp;
for (cp = bp; cp != NULL ;cp = cp->next)
bprep(cp);
}
static bool
scan_ref(bp, reg)
register BLOCK *bp;
register int reg;
{
register INST *ip;
if (bp == NULL)
return FALSE;
if (bp->rref & reg)
return TRUE;
if (bp->rset & reg)
return FALSE;
if (bp->flags & B_MARK)
return FALSE;
if (bp->flags & B_RET)
return FALSE;
bp->flags |= B_MARK;
if (scan_ref(bp->bcond, reg))
return TRUE;
if (scan_ref(bp->bfall, reg))
return TRUE;
for (ip = bp->first; ip != NULL ;ip = ip->next) {
if (ip->opcode == DC && (ip->flags & LENL)) {
BLOCK *db;
if (is_astr(ip->src.amode) && (ip->src.astr != NULL) &&
(db = getsym(ip->src.astr)) != NULL)
if (scan_ref(db, reg))
return TRUE;
}
}
return FALSE;
}
/*
* is_live(bp, reg) - is 'reg' live at the end of block 'bp'
*
* Look ahead through the traversal graph to see what might happen to the
* given register. If we can find any reachable block that references 'reg'
* before setting it, the register is live. Scanning stops when the register
* is set, we loop back to the starting block, or the function returns.
*/
static bool
is_live(bp, reg)
register BLOCK *bp;
register int reg;
{
register INST *ip;
register BLOCK *cp;
/*
* Clear all the mark bits
*/
for (cp = fhead; cp != NULL ;cp = cp->next)
cp->flags &= ~B_MARK;
bp->flags |= B_MARK;
if (scan_ref(bp->bfall, reg))
return TRUE;
if (scan_ref(bp->bcond, reg))
return TRUE;
for (ip = bp->first; ip != NULL ;ip = ip->next) {
if (ip->opcode == DC && (ip->flags & LENL)) {
BLOCK *db;
if (is_astr(ip->src.amode) && (ip->src.astr != NULL) &&
(db = getsym(ip->src.astr)) != NULL)
if (scan_ref(db, reg))
return TRUE;
}
}
return FALSE;
}
/*
* bflow() - live/dead analysis for a given block
*
* Work backward from the end of the block, checking the status of registers.
* To start with, figure out the state of each register as of the end of the
* block. Then work backward, checking registers only as necessary.
*/
static void
bflow(bp)
BLOCK *bp;
{
register INST *ip;
register int live = 0;
register int reg;
/*
* Figure out what's alive at the end of this block.
*/
for (reg = FIRSTREG; reg <= LASTREG ;reg++) {
if (is_live(bp, RM(reg)))
live |= RM(reg);
}
/*
* Now work through the instructions in the block.
*/
for (ip = bp->last; ip != NULL ;ip = ip->prev) {
ip->live = live;
for (reg = FIRSTREG; reg <= LASTREG ;reg++) {
if (ip->rref & RM(reg))
live |= RM(reg);
else if (ip->rset & RM(reg))
live &= ~RM(reg);
}
}
}
void
rhealth(bp, do_prep)
BLOCK *bp;
bool do_prep;
{
register BLOCK *cp;
if (do_prep)
fprep(bp);
for (cp = bp; cp != NULL ;cp = cp->next)
bflow(cp);
}